package com.seadragon.apps.doctorcard.service.impl;

import static com.seadragon.apps.doctorcard.model.DoctorCardConstants.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.seadragon.apps.doctorcard.model.Chat;
import com.seadragon.apps.doctorcard.model.ChatContact;
import com.seadragon.apps.doctorcard.model.ChatMessage;
import com.seadragon.apps.doctorcard.model.Contact;
import com.seadragon.apps.doctorcard.model.DoctorCardResult;
import com.seadragon.apps.doctorcard.model.Message;
import com.seadragon.apps.doctorcard.repository.ChatContactRepository;
import com.seadragon.apps.doctorcard.repository.ChatMessageRepository;
import com.seadragon.apps.doctorcard.service.ChatMessageService;

@Service("chatMessageService")
public class ChatMessageServiceImpl implements ChatMessageService {
	@Autowired
	private ChatMessageRepository chatMessageRepository;
	
	@Autowired
	private ChatContactRepository chatContactRepository;
	
	@Override
	@Transactional
	public ChatMessage save(ChatMessage chatMessage) {
		return chatMessageRepository.save(chatMessage);
	}

	@Override
	public ChatMessage findById(long id) {
		return chatMessageRepository.findOne(id);
	}

	@Override
	public DoctorCardResult findMessagesByChat(Contact contact, long chatId, int offset, int pageSize) {
		DoctorCardResult result = new DoctorCardResult();
		Chat chat = new Chat(chatId);
		ChatContact  chatContact = chatContactRepository.findByChatAndContact(chat, contact);
		if(chatContact == null){
			result.setStatus(RETURN_FAIL);
			result.addErrorCode(ERROR_CODE_NOT_YOUR_CHAT);
		}else{
			Page<ChatMessage> chatMessages = chatMessageRepository.findByChatAndDatePublishedAfterOrderByDatePublishedDesc(chat, chatContact.getDateJoined(), new PageRequest(offset, pageSize));
			List<Message> messages = new ArrayList<Message>();
			
			Iterator<ChatMessage> iter = chatMessages.iterator();
			while(iter.hasNext()){
				ChatMessage cm = iter.next();
				Message message = cm.getMessage();
				message.setPublisher(cm.getPublisher());
				messages.add(message);				
			}
			result.setStatus(RETURN_SUCCESS);
			result.setData(messages);
		}
		result.setLoginedContact(contact);
		return result;
	}

	@Override
	public DoctorCardResult findMessagesByChatAndDate(Contact contact, long chatId, int offset, int pageSize, Date dateLastRetrieved) {
		DoctorCardResult result = new DoctorCardResult();
		Chat chat = new Chat(chatId);
		ChatContact  chatContact = chatContactRepository.findByChatAndContact(chat, contact);
		if(chatContact == null){
			result.setStatus(RETURN_FAIL);
			result.addErrorCode(ERROR_CODE_NOT_YOUR_CHAT);
		}else{
			Page<ChatMessage> chatMessages = null;
			if(chatContact.getDateJoined().after(dateLastRetrieved)){
				chatMessages = chatMessageRepository.findByChatAndDatePublishedAfterOrderByDatePublishedDesc(chat, chatContact.getDateJoined(), new PageRequest(offset, pageSize));
			}else{
				chatMessages = chatMessageRepository.findByChatAndDatePublishedAfterOrderByDatePublishedDesc(chat, dateLastRetrieved, new PageRequest(offset, pageSize));
			}
			List<Message> messages = new ArrayList<Message>();
			
			Iterator<ChatMessage> iter = chatMessages.iterator();
			while(iter.hasNext()){
				ChatMessage cm = iter.next();
				Message message = cm.getMessage();
				message.setPublisher(cm.getPublisher());
				messages.add(message);				
			}
			result.setStatus(RETURN_SUCCESS);
			result.setData(messages);
		}
		result.setLoginedContact(contact);
		return result;
	}

	@Override
	@Transactional
	public DoctorCardResult sendMessage(Contact contact, Chat chat, Message message){
		DoctorCardResult response = new DoctorCardResult();

		ChatContact cc = chatContactRepository.findByChatAndContact(chat, contact);
		if(cc == null){
			response.setStatus(RETURN_FAIL);
			response.addErrorCode(ERROR_CODE_NOT_YOUR_CHAT);
			return response;
		}
		
		message.setAuthor(contact);
		message.setDateCreated(new Date());

		ChatMessage chatMessage = new ChatMessage(chat, message);
		chatMessage.setDatePublished(new Date());
		chatMessage.setPublisher(contact);
		ChatMessage cmSaved = chatMessageRepository.save(chatMessage);
		if(cmSaved == null){
			response.setStatus(RETURN_FAIL);
			response.addErrorCode(ERROR_CODE_FAIL_TO_SAVE_CHAT_MESSAGE);
			return response;
		}
		response.setStatus(RETURN_SUCCESS);
		return response;
	}

	@Override
	@Transactional
	public DoctorCardResult forwardMessage(Contact contact, Chat chat, long messageId){
		DoctorCardResult response = new DoctorCardResult();

		ChatContact cc = chatContactRepository.findByChatAndContact(chat, contact);
		if(cc == null){
			response.setStatus(RETURN_FAIL);
			response.addErrorCode(ERROR_CODE_NOT_YOUR_CHAT);
			return response;
		}
		ChatMessage chatMessage = new ChatMessage(chat, new Message(messageId));
		chatMessage.setDatePublished(new Date());
		chatMessage.setPublisher(contact);
		ChatMessage cmSaved = chatMessageRepository.save(chatMessage);
		if(cmSaved == null){
			response.setStatus(RETURN_FAIL);
			response.addErrorCode(ERROR_CODE_FAIL_TO_SAVE_CHAT_MESSAGE);
			return response;
		}
		response.setStatus(RETURN_SUCCESS);
		return response;
	}
}
